var _http = require('http');
var _https = require('https');
var common = require('./commonUtils');
var logger = require('log4js').getLogger('common-http');
var Promise = require('promise');
var iconv = require('iconv-lite');
iconv.extendNodeEncodings();
var http = {};
var defaultHeaders = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36'
};
var defaultEncoding = 'UTF8';

var timeout = 1000 * 60 * 2;
http.post = function (url, options, callback) {
    var _options = {
        hostname: getHost(url),
        port: getPort(url),
        path: getPath(url),
        method: 'POST',
        headers: options.headers ? options.headers : defaultHeaders
    };
    _common(_options, options, url, callback);
};
http.get = function (url, options, callback) {
    var _options = {
        hostname: getHost(url),
        port: getPort(url),
        path: getPath(url),
        method: 'GET',
        headers: options.headers ? options.headers : defaultHeaders
    };
    _common(_options, options, url, callback);
};


http.pmGet = function (url, options) {
    return new Promise(function (fulfill, reject) {
        var _options = {
            hostname: getHost(url),
            port: getPort(url),
            path: getPath(url),
            method: 'GET',
            headers: options.headers ? options.headers : defaultHeaders
        };
        _pmCommon(_options, options, url, fulfill, reject);
    });
};


http.pmPost = function (url, options) {
    return new Promise(function (fulfill, reject) {
        var _options = {
            hostname: getHost(url),
            port: getPort(url),
            path: getPath(url),
            method: 'POST',
            headers: options.headers ? options.headers : defaultHeaders
        };
        _pmCommon(_options, options, url, fulfill, reject);
    });
};



var _common = function(_options, options, url, callback){
    logger.debug(_options);
    var req = getProtocol(url).request(_options, function (res) {
        /*if(options.encoding){
            res.setEncoding('binary');
        }*/
        var size = 0;
        var chunks = [];
        res.on('data', function (chunk) {
            size += chunk.length;
            chunks.push(chunk);
        });
        res.on('end', function () {
            var rs = Buffer.concat(chunks, size).toString(options.encoding ? options.encoding : defaultEncoding);
            //logger.debug('http result : ' + rs);
            rs = JSON.parse(rs)
            return callback({data : rs, status :  res.statusCode});
        });
    });
    req.on('error', function (e) {
        logger.error(e);
        logger.error('http error, url: ', url);
        return callback(e);
    });

    !options.data || req.write(
        typeof options.data === 'object' ? (JSON.stringify(options.data)) : options.data,
        options.encoding ? options.encoding : defaultEncoding);

    req.setTimeout(options.timeout ? options.timeout : timeout, function () {
        logger.error('http  timeout, url: ', url);
        return callback(new Error('http  timeout, url: ' + url));
    });
    req.end();
};

var _pmCommon = function(_options, options, url, fulfill, reject){
    logger.debug(_options);
    var req = getProtocol(url).request(_options, function (res) {
        /*if(options.encoding){
            res.setEncoding('binary');
        }*/
        var size = 0;
        var chunks = [];
        res.on('data', function (chunk) {
            size += chunk.length;
            chunks.push(chunk);
        });
        res.on('end', function () {
            try {
                var rs = Buffer.concat(chunks, size).toString(options.encoding ? options.encoding : defaultEncoding);
                //logger.debug('http result : ' + rs);
                fulfill({data : rs, status :  res.statusCode});
            } catch (e) {
                reject(e);
            }
        });
    });
    req.on('error', function (e) {
        logger.error(e);
        logger.error('http error, url: ', url);
        reject(e);
    });

    !options.data || req.write(
        typeof options.data === 'object' ? (JSON.stringify(options.data)) : options.data,
        options.encoding ? options.encoding : defaultEncoding);


    req.setTimeout(options.timeout ? options.timeout : timeout, function () {
        logger.error('http timeout, url: ', url);
        reject(new Error('http timeout, url: ' + url));
    });
    req.end();
};

//Parse the url,get the path
//e.g. http://www.google.com/path/another -> /path/another
function getPath(url) {
    var pathPattern = /\w+:\/\/([^\/]+)(\/.+)(\/$)?/i;
    var fullPath = url.match(pathPattern);
    return fullPath ? fullPath[2] : '/';
};

//Parse the url, get the port
//e.g. http://www.google.com/path/another -> 80
//     http://foo.bar:8081/a/b -> 8081
function getPort(url) {
    var hostPattern = /\w+:\/\/([^\/]+)(\/)?/i;
    var domain = url.match(hostPattern);
    var pos = domain[1].indexOf(":");
    if (pos !== -1) {
        domain[1] = domain[1].substr(pos + 1);
        return parseInt(domain[1]);
    } else if (url.toLowerCase().substr(0, 5) === "https") return 443;
    else return 80;
};

//Parse the url,get the host name
//e.g. http://www.google.com/path/another -> www.google.com
var getHost = function getHost(url) {
    var hostPattern = /\w+:\/\/([^\/]+)(\/)?/i;
    var domain = url.match(hostPattern);

    var pos = domain[1].indexOf(":");
    if (pos !== -1) {
        domain[1] = domain[1].substring(0, pos);
    }
    return domain[1];
};

//Get the Protocol
//http://www.google.com/path/another => http
function getProtocol(url) {
    return url.substring(0, url.indexOf(":")) === 'https' ? _https : _http;
};

http.getHost = getHost;
module.exports = http;